﻿using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using PlusPlusPaint.Layers.VisualObjects;

namespace PlusPlusPaint.Tools
{
    class BrushTool : VisualObjectLayerStoringTool
    {
        #region member variables
        List<Point> pointList = new List<Point>();
        #endregion

        #region properties
        public override bool DemandsNewLayer
        {
            get
            {
                return false;
            }
        }

        public override bool AcceptsNewLayer
        {
            get
            {
                return true;
            }
        }
        #endregion

        #region private methods
        private void UpdatePreview(Point start, Point end)
        {
            Layer.Invoke<LineSegmentGroup>((o) =>
            {
                if (start != end)
                    o.ResizeToBeIn(start, end);
                o.AddPoint(pointList[pointList.Count - 1]);
            });
            if (pointList.Count > 1)
                using (Pen p = new Pen(this.Colour, this.BrushSize))
                    Graphics.FromImage(Preview).DrawLines(p, pointList.ToArray());
        }

        private void Complete()
        {
            Layer.Invoke<LineSegmentGroup>((o) =>
            {
                o.Colour = this.Colour;
                o.BrushSize = this.BrushSize;
            });
        }

        private void clearPreview()
        {
            Graphics.FromImage(Preview).Clear(Color.Transparent);
        }

        private Rectangle GetBoundingBox()
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddLines(pointList.ToArray());
            RectangleF rectF = gp.GetBounds();
            Rectangle rect = new Rectangle((int)rectF.X, (int)rectF.Y, (int)rectF.Width, (int)rectF.Height);
            return rect;
        }
        #endregion

        #region overrides
        public override bool AcceptableLayer(Layers.ILayer l)
        {
            return l.CanFreeDraw;
        }

        public override Layers.ILayer SuggestNewLayer()
        {
            return new Layers.VisualObjectLayer();
        }

        public override void HandleMouseDown(System.Windows.Forms.MouseEventArgs mea)
        {
            pointList.Add(mea.Location);
            this.UpdatePreview(mea.Location, mea.Location);
        }

        public override void HandleMouseDrag(System.Windows.Forms.MouseEventArgs mea)
        {
            if (mea.Button == System.Windows.Forms.MouseButtons.Left)
            {
                pointList.Add(mea.Location);
                Rectangle rect = GetBoundingBox();
                Point bottomRight = new Point(rect.X + rect.Width, rect.Y + rect.Height);
                clearPreview();
                this.UpdatePreview(rect.Location, bottomRight);
            }
        }

        public override void HandleMouseUp(System.Windows.Forms.MouseEventArgs mea)
        {
            base.HandleMouseUp(mea);
            clearPreview();
            this.Complete();
            pointList.Clear();
            this.Layer.Invalidate();
        }
        #endregion
    }
}
